package com.emeraldparser.collect;

import java.util.Set;

import com.google.common.collect.Multiset;

/**
 * A directed multigraph.
 * 
 * <p>Edges may be added in several ways. For example, these are various ways to add
 * an edge whose source is "A", whose destination is "B" and whose label is "A-B" to a graph:</p>
 * 
 * <p><code>graph.edges().add(ImmutableEdge.create("A", "B", "A-B"));</code></p>
 * 
 * <p><code>graph.edges().add(ImmutableEdge.from("A").to("B").labelled("A-B"));</code></p>
 * 
 * <p><code>graph.edges().from("A").to("B").labels().add("A-B");</code></p>
 * 
 * <p><code>graph.edges().from("A").labelled("A-B").destinations().add("B");</code></p>
 * 
 * <p><code>graph.edges().to("B").labelled("A-B").sources().add("A");</code></p>
 * 
 * <p><code>graph.edges().touching("A").vertices();</code></p>
 * 
 * @author Adam Paynter
 *
 * @param <V> The type of the vertices
 * @param <E> The type of the edge <em>labels</em>
 */
public interface Graph<V, E> {

	Set<V> vertices();

	EdgeMultiset<V, E> edges();

	public static interface Edge<V, E> {

		V getSource();

		V getDestination();

		E getLabel();

		@Override
		int hashCode();

		@Override
		boolean equals(Object obj);

	}

	public static interface EdgeMultiset<V, E> extends Multiset<Edge<V, E>> {

		EdgeMultiset<V, E> from(V source);

		EdgeMultiset<V, E> to(V destination);

		EdgeMultiset<V, E> labelled(E label);

		Multiset<V> sources();

		Set<V> sourceSet();

		Multiset<V> destinations();

		Set<V> destinationSet();

		Multiset<E> labels();

		Set<E> labelSet();

	}

}
